package com.cyx.netty.gateway.client.channel;

import static io.netty.handler.codec.http.HttpHeaderNames.CONTENT_LENGTH;
import static io.netty.handler.codec.http.HttpHeaderValues.KEEP_ALIVE;
import static io.netty.handler.codec.http.HttpHeaders.Names.ACCESS_CONTROL_ALLOW_CREDENTIALS;
import static io.netty.handler.codec.http.HttpHeaders.Names.ACCESS_CONTROL_ALLOW_HEADERS;
import static io.netty.handler.codec.http.HttpHeaders.Names.ACCESS_CONTROL_ALLOW_ORIGIN;
import static io.netty.handler.codec.http.HttpHeaders.Names.CONNECTION;

import com.cyx.netty.gateway.support.ServerWebExchange;
import com.cyx.netty.gateway.util.ExpiryMap;
import com.cyx.netty.gateway.util.cache.ChannelCacheManager;
import io.netty.channel.*;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpUtil;

import io.netty.util.ReferenceCountUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ProxyClientChannelInboundHandlerAdapter extends ChannelInboundHandlerAdapter {

    private final Logger logger = LoggerFactory.getLogger(ProxyClientChannelInboundHandlerAdapter.class);

    private ServerWebExchange serverWebExchange;

    public ProxyClientChannelInboundHandlerAdapter(ServerWebExchange serverWebExchange) {
        this.serverWebExchange = serverWebExchange;
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg)  {

        Channel channel = serverWebExchange.getChannelHandlerContext().channel();
        FullHttpResponse response = (FullHttpResponse) msg;
        response.headers().set(ACCESS_CONTROL_ALLOW_ORIGIN, "*");
        response.headers().set(ACCESS_CONTROL_ALLOW_HEADERS,"*");
        response.headers().set(ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
        response.headers().setInt(CONTENT_LENGTH, response.content().readableBytes());
        boolean keepAlive = HttpUtil.isKeepAlive(response);
        if (!keepAlive) {
            channel.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
            return;
        }
        response.headers().set(CONNECTION, KEEP_ALIVE);
        channel.writeAndFlush(response);

        logger.info("service channel id"+ channel.id().asShortText()+";client proxy channel id："+ctx.channel().id().asShortText()+"\n");
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        super.channelActive(ctx);

        Channel channel = serverWebExchange.getChannelHandlerContext().channel();
        ChannelCacheManager.put(channel.id().asShortText(),ctx.channel());
        logger.error("connect channel："+ctx.channel().id().asShortText());
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        super.channelInactive(ctx);
       ctx.flush();
    }

    /**
     * channelReadComplete channel 通道 Read 读取 Complete 完成
     * 在通道读取完成后会在这个方法里通知，对应可以做刷新操作 ctx.flush()
     */
    public void channelReadComplete(ChannelHandlerContext ctx) {
        ctx.flush();
    }

    /**
     * exceptionCaught exception 异常 Caught 抓住
     * 抓住异常，当发生异常的时候，可以做一些相应的处理，比如打印日志、关闭链接
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        //super.exceptionCaught(ctx, cause);

        logger.error("exec info：\r\n" + cause.getMessage());
        Channel channel = serverWebExchange.getChannelHandlerContext().channel();
        ChannelCacheManager.remove(channel.id().asShortText());
        ctx.close();
    }
}
